#include "stdafx.h"
#include "HTTPContent.h"
#include "Tool.h"

#define ETAG_BYTE_SIZE 5 // 对于内存数据,创建ETag时抽取的字节数

HTTPContent::HTTPContent()
	:openType(S_OPEN_NONE),
	contentType(""),
	fileName("")
{
	memset(&this->fileInfo, 0, sizeof(struct _stat32i64));
}


HTTPContent::~HTTPContent()
{
	this->close();
}

void HTTPContent::close()
{
	this->contentType = "";

	this->openType = S_OPEN_NONE;

	this->fileName = "";

	this->memOperator.trunc();
}

bool HTTPContent::open(const char * buffer, unsigned int length, unsigned int type)
{
	if (type == S_OPEN_NONE)
	{
		return false;
	}

	assert(this->memOperator.fSize() == 0);

	if (length == this->write(buffer, length))
	{
		this->openType = type;
	}
	else
	{
		assert(0);
	}

	return this->openType != S_OPEN_NONE;

}

unsigned int HTTPContent::write(const char * buffer, unsigned int length)
{
	return this->memOperator.write(buffer, length);
}

const std::string HTTPContent::lastModifield()
{
	time_t timep;
	
	if (this->openType == S_OPEN_FILE)
	{
		timep = this->fileInfo.st_atime;
	}
	else
	{
		time(&timep);
	}

	struct tm t;   //tm结构指针
	
	localtime_s(&t, &timep);

	char stTmp[30];

	// 转换为字符串并输出
	asctime_s(stTmp, &t);
	std::string a;
	for (int i = 11; i < 19; i++)
	{
		a += stTmp[i];
	}
	return a;
}

std::string HTTPContent::getETag()
{
	std::string  etg("");
	// 打开是文件
	if (this->openType == S_OPEN_FILE)
	{
		// TODO
	}
	else
	{
		char rece[201] = { 0 };
		/*
		 * 将整数转换为字符串
		  value, 是要转换的数字；

		  buffer, 是存放转换结果的字符串；

		  sizeInCharacters, 存放转换结果的字符串长度

		  radix, 是转换所用的基数，2-36。如，2：二进制，10：十进制，16：十六进制
		*/

		int fSize = this->memOperator.fSize();

		_itoa_s(fSize, rece, 10);

		// 如果是内存数据, 根据大小和取若干个字节的16进制字符创建.
		unsigned char szValue[ETAG_BYTE_SIZE + 1];

		for (int i = 0; i < ETAG_BYTE_SIZE; ++i)
		{
			int nUnit = fSize / ETAG_BYTE_SIZE;
			szValue[i] = this->memOperator.getBuffer()[nUnit * i];
		}

		etg = hashCoding(szValue, ETAG_BYTE_SIZE);
		etg.append(":").append(rece);
	}

	return etg;
}

/*获取内容类型*/
std::string HTTPContent::getContentType()
{
	return contentTypeComponent()[this->openType];
}

std::string HTTPContent::getContentTypeByFileName()
{
	// 先这样
	return "text/html";
}

/**/
std::string * HTTPContent::contentTypeComponent()
{
	static std::string* type;

	if (type != NULL)
	{
		return type;
	}

	type = new std::string[5];

	type[0] = "application/octet-stream";

	type[1] = getContentTypeByFileName();

	type[2] = "text/plain";

	type[3] = "text/html";

	type[4] = "text/html";

	return type;
}

size_t HTTPContent::getContentLength()
{
	if (this->openType == S_OPEN_FILE)
	{
		// TODO
	}
	else
	{
		return this->memOperator.fSize();
	}
}

/*
	断点续传也就是从下载断开的哪里，重新接着下载，直到下载完整/可用。
	如果要使用这种断点续传，4个HTTP头不可少的，分别是Range头、Content-Range头、Accept-Ranges头、Content-Length头。
	这里我讲的是服务端，其中要用Range头是因为它是客户端发过来的信息。服务端是响应，而客户端（浏览器）是请求。
*/
std::string HTTPContent::getContentRange()
{
	char szRanges[300] = { 0 };
	if (this->openType == S_OPEN_FILE)
	{
		//sprintf(szRanges, "bytes %lld-%lld/%lld", _from, _to, _fileInf.st_size);
	}
	
	return szRanges;
}


size_t HTTPContent::read(char * buffer, size_t length)
{
	if (this->openType == S_OPEN_FILE)
	{
		// TODO
	}
	else
	{
		return this->memOperator.read(buffer, length);
	}
}
